﻿using Exam.infranstuctrue.Dto.Request.Exam;
using Exam.infranstuctrue.Dto.Respones;
using Exam.infranstuctrue.Dto.Respones.Exam;
using Exam.infranstuctrue.EFCore;
using Exam.infranstuctrue.IOC;
using Exam.infranstuctrue.Tools;
using Exam.infranstuctrue.Tools.Attributes;
using Exam.Service.Interface;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam.Service.Instance
{
    [Iinjection]
    public class TestPaperServer : BaseService, ITestPaperServer
    {
        private readonly ExamIOC _examIOC;

        public TestPaperServer(ExamIOC examIOC)
        {
            _examIOC = examIOC;
        }
        /// <summary>
        /// 获取试卷列表
        /// </summary>
        /// <param name="limit"></param>
        /// <param name="paeg"></param>
        /// <param name="key"></param>
        /// <param name="IsPublic"></param>
        /// <param name="IsBan"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetTestPaper(int page = 1, int limit = 10, string key = "", int IsPublic = -1, int IsBan = -1)
        {
            var testpaper = await _examIOC._examTestPaperEFCore.QueryAll(out int total, page, limit, o => o.TpcreateTime, false, d => d.Tpname.Contains(key)
            && (IsPublic == -1 || d.TpisPublish == IsPublic)
            && (IsBan == -1 || d.TpisBan == IsBan)).ToListAsync();
            var tpids = testpaper.Select(d => d.Tpid).ToList();
            var testpaperdetalis = await _examIOC._examTestPaperDetailEFCore.QueryAll(d => tpids.Contains(d.Tpdtpid)).ToListAsync();
            var qids = testpaperdetalis.Select(d => d.Tpdqid).ToList();
            var questions = await _examIOC._examQuestionEFCore.QueryAll(d => qids.Contains(d.Qid)).ToListAsync();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<TestPaperRes> testPaperRes = new List<TestPaperRes>();
            foreach (var item3 in testpaper)
            {
                var testpaperdetali = testpaperdetalis.Where(d => d.Tpdtpid == item3.Tpid).ToList();
                var testpaperdetaliqids = testpaperdetali.Select(d => d.Tpdqid).ToList();
                var question = questions.Where(d => testpaperdetaliqids.Contains(d.Qid)).ToList();
                List<QuestionRes> questionRes = new List<QuestionRes>();
                foreach (var item in question)
                {
                    List<OptionRes> optionRes = new List<OptionRes>();
                    var option = options.Where(d => d.Oqid == item.Qid).ToList();
                    foreach (var item2 in option)
                    {
                        optionRes.Add(new OptionRes
                        {
                            Oid = item2.Oid,
                            Ocontent = item2.Ocontent,
                            OisRight = item2.OisRight,
                            Ocreatetime = item2.Ocreatetime,
                        });
                    }
                    questionRes.Add(new QuestionRes
                    {
                        Qid = item.Qid,
                        Qcontent = item.Qcontent,
                        Qexplain = item.Qexplain,
                        Qanalysi = item.Qanalysi,
                        Qanswer = item.Qanswer,
                        Qauthor = item.Qauthor,
                        QcreateTime = item.QcreateTime,
                        QisBan = item.QisBan,
                        QisCheck = item.QisCheck,
                        QisPublish = item.QisPublish,
                        Qlable = item.Qlable,
                        Qlv = item.Qlv,
                        Qstate = item.Qstate,
                        Qtype = item.Qtype,
                        opiton = optionRes,
                    });
                }
                testPaperRes.Add(new TestPaperRes
                {
                    tpid = item3.Tpid,
                    tpexplain = item3.Tpexplain,
                    tplabel = item3.Tpexplain,
                    tplv = item3.Tplv,
                    tpname = item3.Tpname,
                    passscore = item3.TppassScore,
                    score = item3.TptotalScore,
                    tpcount = item3.Tpcount,
                    tpusecount = item3.TpuseCount,
                    IsBan = item3.TpisBan,
                    IsPublish = item3.TpisPublish,
                });
            }
            return GetResult(1, "试卷列表", data: (new
            {
                total = total,
                data = testPaperRes
            }));
        }
        /// <summary>
        /// 组卷 --随机
        /// </summary>
        /// <param name="count"></param>
        /// <param name="minLv"></param>
        /// <param name="maxLv"></param>
        /// <returns></returns>
        public async Task<ApiResult> ConstituteTestPage(int count, int minLv, int maxLv)
        {
            if (count < 0)
            {
                return GetResult(0, "参数错误");
            }
            if (minLv < count)
            {
                return GetResult(0, "参数错误");
            }
            if (maxLv > count * 10)
            {
                return GetResult(0, "参数错误");
            }
            var baginMinLv = minLv;
            var endMaxLv = maxLv;
            List<int> group = new List<int>() { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            List<int?> list = new();
            for (var i = 1; i <= count; i++)
            {
                var min = baginMinLv - (count - i) * 10;
                if (min <= 0)
                {
                    min = 1;
                }
                var max = endMaxLv - (count - i);
                if (max > 10)
                {
                    max = 11;
                }
                var rd = Config.GetRandom(min, max);
                baginMinLv -= rd;
                endMaxLv -= rd;
                list.Add(rd);
                group[rd - 1]++;
            }
            var question = await _examIOC._examQuestionEFCore.QueryAll(d => EF.Functions.Random(), true, o => o.QisBan == 0 && o.QisPublish == 1).ToListAsync();
            var qids = question.Select(d => d.Qid).ToList();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<QuestionRes> questionres = new List<QuestionRes>();
            for (int i = 0; i < group.Count(); i++)
            {
                var data = question.Where(d => d.Qlv == (i + 1)).ToList();
                var jieguo = data.Skip(1).Take(group[i]).OrderBy(d => d.Qlv).ToList();

                foreach (var item2 in jieguo)
                {
                    List<OptionRes> optionres = new List<OptionRes>();
                    var option = options.Where(d => item2.Qid == d.Oqid).ToList();
                    foreach (var item in option)
                    {
                        optionres.Add(new OptionRes
                        {
                            Oid = item.Oid,
                            Oqid = item.Oqid,
                            Ocontent = item.Ocontent,
                            OisRight = item.OisRight,
                        });
                    }
                    questionres.Add(new QuestionRes
                    {
                        Qid = item2.Qid,
                        Qcontent = item2.Qcontent,
                        Qexplain = item2.Qexplain,
                        Qanswer = item2.Qanswer,
                        Qlable = item2.Qlable,
                        Qlv = item2.Qlv,
                        opiton = optionres,
                    });
                }
            }
            return GetResult(1, "随机试题", questionres);
        }
        /// <summary>
        /// 组卷  --人工
        /// </summary>
        /// <param name="lable"></param>
        /// <returns></returns>
        public async Task<ApiResult> ArtificialTestPage(int page, int limit, string key = "")
        {
            var questions = await _examIOC._examQuestionEFCore.QueryAll(out int total, page, limit, o => o.QcreateTime, false, d => d.Qcontent.Contains(key) && d.QisPublish == 1 && d.QisBan == 0).ToListAsync();
            var qids = questions.Select(d => d.Qid).ToList();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<QuestionRes> questionRes = new List<QuestionRes>();
            foreach (var item2 in questions)
            {
                List<OptionRes> optionRes = new List<OptionRes>();
                var option = options.Where(d => d.Oqid == item2.Qid).ToList();
                foreach (var item in option)
                {
                    optionRes.Add(new OptionRes
                    {
                        Oid = item.Oid,
                        Oqid = item.Oqid,
                        Ocontent = item.Ocontent,
                        OisRight = item.OisRight
                    });
                }
                questionRes.Add(new QuestionRes
                {
                    Qanalysi = item2.Qanalysi,
                    Qanswer = item2.Qanswer,
                    Qauthor = item2.Qauthor,
                    Qcontent = item2.Qcontent,
                    QcreateTime = item2.QcreateTime,
                    Qexplain = item2.Qexplain,
                    Qid = item2.Qid,
                    Qlable = item2.Qlable,
                    Qtype = item2.Qtype,
                    Grade = 0,
                    Qlv = item2.Qlv,
                    opiton = optionRes
                });
            }
            return GetResult(1, "组卷 --人工", data: (new
            {
                total = total,
                data = questionRes
            }));
        }
        /// <summary>
        /// 添加试卷
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> RandomAddTestPage(AddTestPageDto dto)
        {
            if (dto.tplv > 0 && dto.tplv <= 3)
            {
                dto.tplv = 1;
            }
            else if (dto.tplv >= 4 && dto.tplv <= 6)
            {
                dto.tplv = 2;
            }
            else if (dto.tplv >= 7)
            {
                dto.tplv = 3;
            }
            var tpid = Config.GUID();
            ExamTestPaper examTestPaper = new ExamTestPaper()
            {
                Tpid = tpid,
                Tpcount = dto.tpcount,
                TpcreateTime = DateTime.Now,
                Tpdesc = "",
                Tpexplain = dto.tpexplain,
                TpisBan = 0,
                TpisPublish = 0,
                Tplabels = dto.tplabels,
                Tplv = dto.tplv,
                Tpmode = dto.tpmodel,
                Tpname = dto.tpname,
                TppassScore = dto.tppasssocre,
                Tpstate = 1,
                TptotalScore = dto.tpsocre,
                Tptype = dto.tptype,
                TpuseCount = 0,
            };
            List<ExamTestPaperDetail> examTest = new List<ExamTestPaperDetail>();
            foreach (var item in dto.questions)
            {
                examTest.Add(new ExamTestPaperDetail
                {
                    Tpdid = Config.GUID(),
                    Tpdtpid = tpid,
                    Tpdscore = item.qscore,
                    Tpdqid = item.qid,
                    Tpdno = null,
                });

            }
            _examIOC._examTestPaperEFCore.Add(examTestPaper);
            await _examIOC._examTestPaperEFCore.SaveChangesAsync();
            _examIOC._examTestPaperDetailEFCore.AddRange(examTest);
            await _examIOC._examTestPaperDetailEFCore.SaveChangesAsync();
            var result = _examIOC._examTestPaperEFCore.Transactions(_examIOC._examTestPaperEFCore, _examIOC._examTestPaperDetailEFCore);
            if (result == true)
            {
                return GetResult(1, "添加成功");
            }
            return GetResult(0, "操作失败");
        }
        /// <summary>
        /// 删除试卷
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> DeleteTestPaper(List<AddTestPageDto> dto)
        {
            var tpids = dto.Select(d => d.tpid).ToList();
            var testpaper = await _examIOC._examTestPaperEFCore.QueryAll(d => tpids.Contains(d.Tpid)).ToListAsync();
            var testpaperdetali = await _examIOC._examTestPaperDetailEFCore.QueryAll(d => tpids.Contains(d.Tpdtpid)).ToListAsync();
            foreach (var item in testpaper)
            {
                if (item.TpisPublish == 1)
                {
                    return GetResult(0, "该试卷已发布请先取消发布");
                }
                if (item.TpuseCount > 0)
                {
                    return GetResult(0, "试卷已被使用不可删除");
                }
            }
            _examIOC._examTestPaperEFCore.DeleteRange(testpaper);
            _examIOC._examTestPaperDetailEFCore.DeleteRange(testpaperdetali);
            var result = _examIOC._examTestPaperEFCore.Transactions(_examIOC._examTestPaperEFCore, _examIOC._examTestPaperDetailEFCore);
            return GetResult(result == true ? 1 : 0, result == true ? "删除成功" : "删除失败");
        }
        /// <summary>
        /// 获取单个试卷
        /// </summary>
        /// <param name="tpid"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetEchoTestPaper(string tpid, int page, int limit, string key = "")
        {
            var testpaper = await _examIOC._examTestPaperEFCore.QueryAll(d => d.Tpid == tpid).FirstOrDefaultAsync();
            var testpaperdetali = await _examIOC._examTestPaperDetailEFCore.QueryAll(d => d.Tpdtpid.Contains(tpid)).ToListAsync();
            var qids = testpaperdetali.Select(d => d.Tpdqid).ToList();
            var questions = await _examIOC._examQuestionEFCore.QueryAll(out int total, page, limit, o => o.QcreateTime, false, d => qids.Contains(d.Qid) && d.Qcontent.Contains(key)).ToListAsync();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<QuestionRes> questionRes = new List<QuestionRes>();
            foreach (var item in questions)
            {
                List<OptionRes> optionRes = new List<OptionRes>();
                var option = options.Where(d => d.Oqid == item.Qid).ToList();
                foreach (var item2 in option)
                {
                    optionRes.Add(new OptionRes
                    {
                        Oid = item2.Oid,
                        Ocontent = item2.Ocontent,
                        OisRight = item2.OisRight,
                        Ocreatetime = item2.Ocreatetime,
                    });
                }
                questionRes.Add(new QuestionRes
                {
                    Qid = item.Qid,
                    Qcontent = item.Qcontent,
                    Qexplain = item.Qexplain,
                    Qanalysi = item.Qanalysi,
                    Qanswer = item.Qanswer,
                    Qauthor = item.Qauthor,
                    QcreateTime = item.QcreateTime,
                    QisBan = item.QisBan,
                    QisCheck = item.QisCheck,
                    QisPublish = item.QisPublish,
                    Qlable = item.Qlable,
                    Qlv = item.Qlv,
                    Qstate = item.Qstate,
                    Qtype = item.Qtype,
                    opiton = optionRes,
                });
            }
            TestPaperRes testPaperRes = new TestPaperRes()
            {
                tpid = testpaper.Tpid,
                tpcount = testpaper.Tpcount,
                tpexplain = testpaper.Tpexplain,
                tplabel = testpaper.Tplabels,
                tplv = testpaper.Tplv,
                tpname = testpaper.Tpname,
                tpusecount = testpaper.TpuseCount,
                score = testpaper.TptotalScore,
                passscore = testpaper.TppassScore,
                IsPublish = testpaper.TpisPublish,
                IsBan = testpaper.TpisBan,
                question = questionRes,
            };
            return GetResult(1, "单个试卷", data:(new { 
            total= total,
            data = testPaperRes
            }));
        }
        /// <summary>
        /// 修改试卷
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> UpdateTestPaper(AddTestPageDto dto)
        {
            var testpaper = await _examIOC._examTestPaperEFCore.QueryAll(d => d.Tpid == dto.tpid).FirstOrDefaultAsync();
            if (testpaper == null)
            {
                return GetResult(0, "试卷ID错误");
            }
            var arrang = await _examIOC._examArrangEFCore.QueryAll(d => d.Atpid == dto.tpid).FirstOrDefaultAsync();
            if (arrang != null)
            {
                if (arrang.AbeginTime < DateTime.Now)
                {
                    return GetResult(0, "考试已开始不可以修改");
                }
                if (testpaper.TpisPublish == 1)
                {
                    return GetResult(0, "请先取消发布在修改");
                }
                if (testpaper.TpuseCount > 0)
                {
                    return GetResult(0, "已经使用不可修改");
                }
            }

            testpaper.Tpexplain = dto.tpexplain;
            testpaper.Tplabels = dto.tplabels;
            testpaper.Tpname = dto.tpname;
            testpaper.TppassScore = dto.tppasssocre;

            _examIOC._examTestPaperEFCore.Update(testpaper);
            var result = _examIOC._examTestPaperEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "修改成功" : "修改失败");
        }
        /// <summary>
        /// 是否发布
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> IsPublic(List<AddTestPageDto> dto)
        {
            var tpids = dto.Select(d => d.tpid).ToList();
            var testpaper = await _examIOC._examTestPaperEFCore.QueryAll(d => tpids.Contains(d.Tpid)).ToListAsync();
            foreach (var item in testpaper)
            {
                if (item.TpisPublish == 1)
                {
                    item.TpisPublish = 0;
                }
                else
                {
                    item.TpisPublish = 1;
                }
            }
            _examIOC._examTestPaperEFCore.UpdateRange(testpaper);
            var result = _examIOC._examTestPaperEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "修改成功" : "修改失败");
        }
        /// <summary>
        /// 是否禁用
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> IsBan(List<AddTestPageDto> dto)
        {
            var tpids = dto.Select(d => d.tpid).ToList();
            var testpaper = await _examIOC._examTestPaperEFCore.QueryAll(d => tpids.Contains(d.Tpid)).ToListAsync();
            foreach (var item in testpaper)
            {
                if (item.TpisBan == 1)
                {
                    item.TpisBan = 0;
                }
                else
                {
                    item.TpisBan = 1;
                }
            }
            _examIOC._examTestPaperEFCore.UpdateRange(testpaper);
            var result = _examIOC._examTestPaperEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "修改成功" : "修改失败");
        }
    }
}
